#
#      Copyright 2011 Miranda, Tom
#       
#       Licensed under the Apache License, Version 2.0 (the "License");
#       you may not use this file except in compliance with the License.
#       You may obtain a copy of the License at
#
#          http://www.apache.org/licenses/LICENSE-2.0
#
#       Unless required by applicable law or agreed to in writing, software
#       distributed under the License is distributed on an "AS IS" BASIS,
#       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#       See the License for the specific language governing permissions and
#       limitations under the License.
#
#	$Id: sage.py 82 2011-08-10 01:38:25Z derek@battams.ca $

import mc, sage, time
from datetime import date
from time import sleep, strftime
import os.path as path

def mediaFileToListItem(mf):
	try:
		from config import mediaPathMapper

		item = mc.ListItem(mc.ListItem.MEDIA_VIDEO_EPISODE)
		item.SetProperty('MediaFileID', str(mf['MediaFileID']))
		item.SetLabel(mf['MediaTitle'])
		item.SetTVShowTitle(mf['MediaTitle'])
		item.SetPath(mediaPathMapper.convertPath(mf['SegmentFiles'][0]))
		item.SetProperty('NumberOfSegments', str(mf['NumberOfSegments']))
		numberOfSegments = int(mf['NumberOfSegments'])
		i = 0
		while 1:
			try:
				item.SetProperty("Segment"+str(i), mediaPathMapper.convertPath(mf['SegmentFiles'][i]))
				i += 1
			except IndexError:
				break
		item.SetContentType('video/' + path.splitext(item.GetPath())[1][1:])
		duration = int(mf['FileDuration'] // 1000)
		item.SetDuration(duration)
		# FIXME
		#print "SAGEBOXEE:: DURATION %s" % duration
		#print "SAGEBOXEE:: SET DURATION TO %s" % item.GetDuration()
		item.SetProperty('PercentTest', '0.75')	# FIXME TEST
		item.SetSize(mf['Size'])
		item.SetAddToHistory(True)
		if (mf['IsLibraryFile']):
			item.SetProperty('IsLibraryFile', str(mf['IsLibraryFile']))
		item.SetProperty('MediaFileEncoding', mf['MediaFileEncoding'])
		item.SetProperty('MediaFileFormatDescription', mf['MediaFileFormatDescription'])
		item.SetProperty('FormattedDuration', _getHoursMinutes(mf['FileDuration'] // 1000))
		if(mf.has_key('Airing') and mf['Airing'].has_key('Show')):
			show = mf['Airing']['Show']
			item.SetProperty('ShowExternalID', show['ShowExternalID'])
			if(show.has_key('ShowYear') and show['ShowYear'] != ''):
				item.SetYear(int(show['ShowYear']))
			if(show.has_key('RolesInShow')):
				roles = show['RolesInShow']
				try:
					# ListItem only allows for one Writer credit, sorry to the rest of you!
					i = roles.index('Writer')
					item.SetWriter(show['PeopleListInShow'][i])
				except ValueError:
					pass

				try:
					i = roles.index('Director')
					item.SetDirector(show['PeopleListInShow'][i])
				except ValueError:
					pass

				skippedRoles = ['Writer', 'Director']
				for role in roles:
					if(role in skippedRoles):
						continue
					skippedRoles.append(role)
					mc.LogDebug('Adding role "%s"...' % role)
					i = -1
					while 1:
						try:
							i = roles.index(role, i + 1)
							person = show['PeopleAndCharacterListInShow'][i]
							item.AddCastAndRole(person, role)
						except ValueError:
							break

			if(show.has_key('ShowEpisode') and show['ShowEpisode'] != ''):
				item.SetTitle(show['ShowEpisode'])
			if(show.has_key('OriginalAiringDate') and show['OriginalAiringDate'] > 0):
				origDate = date.fromtimestamp(float(show['OriginalAiringDate'] // 1000))
				item.SetDate(origDate.year, origDate.month, origDate.day)
			if(show.has_key('ShowEpisode') and show['ShowEpisode'] != ''):
				item.SetTitle(show['ShowEpisode'])
			if(show.has_key('ShowCategoriesString') and show['ShowCategoriesString'] != ''):
				item.SetGenre(show['ShowCategoriesString'])
			if(show.has_key('ShowSeasonNumber') and show['ShowSeasonNumber'] > 0):
				item.SetSeason(show['ShowSeasonNumber'])
			if(show.has_key('ShowEpisodeNumber') and show['ShowEpisodeNumber'] > 0):
				item.SetEpisode(show['ShowEpisodeNumber'])
			if(show.has_key('ShowDescription') and show['ShowDescription'] != ''):
				item.SetDescription(show['ShowDescription'])
			if(show.has_key('IsShowFirstRun') and show['IsShowFirstRun']):
				item.SetProperty('IsShowFirstRun', str(show['IsShowFirstRun']))
			if(show.has_key('ShowRated') and show['ShowRated'] != ''):
				item.SetContentRating(show['ShowRated'])

		if(mf.has_key('Airing')):
			airing = mf['Airing']
			item.SetProperty('AiringID', str(airing['AiringID']))
			if(airing.has_key('IsWatched') and airing['IsWatched']):
				item.SetProperty('IsWatched', str(airing['IsWatched']))
			if (airing.has_key('IsAiringHDTV') and airing['IsAiringHDTV']):
				item.SetProperty('IsHDTV', 'True')
			if(airing.has_key('ExtraAiringDetails')):
				item.SetProperty('ExtraAiringDetails', airing['ExtraAiringDetails'])
				if (airing['ExtraAiringDetails'].find('HDTV') != -1):
					item.SetProperty('IsHDTV', 'True')
			if(airing.has_key('ParentalRating') and airing['ParentalRating'] != ''):
				item.SetContentRating(airing['ParentalRating'])
			if(airing.has_key('AiringChannelName')):
				item.SetStudio(airing['AiringChannelName'])
				item.SetProperty('AiringChannelName', airing['AiringChannelName'])
			if(airing.has_key('AiringChannelNumber')):
				item.SetProperty('AiringChannelNumber', airing['AiringChannelNumber'])
			if(airing.has_key('IsFavorite') and airing['IsFavorite']):
				item.SetProperty('IsFavorite', str(airing['IsFavorite']))
			if(airing.has_key('IsManualRecord') and airing['IsManualRecord']):
				item.SetProperty('IsManualRecord', str(airing['IsManualRecord']))
			if(airing.has_key('IsDontLike') and airing['IsDontLike']):
				item.SetProperty('IsDontLike', str(airing['IsDontLike']))
			if(airing.has_key('IsWatchedCompletely') and airing['IsWatchedCompletely']):
				item.SetProperty('IsWatchedCompletely', str(airing['IsWatchedCompletely']))
			if(airing.has_key('IsNotManualOrFavorite')):
				item.SetProperty('IsNotManualOrFavorite', str(airing['IsNotManualOrFavorite']))
			# Set AiringStartTime and AiringEndTime.
			if(airing.has_key('AiringStartTime')):
				startTime = float(airing['AiringStartTime'] // 1000)
				airDate = date.fromtimestamp(startTime)
				airTime = strftime('%H:%M', time.localtime(startTime))
				item.SetProperty('AiringStartTime', str(airDate.month) + '/' + str(airDate.day) + '/' + str(airDate.year) + ' ' + airTime)
				item.SetProperty('AiringStartTimeMillis', str(airing['AiringStartTime']))
					
				# Set AiringEndTime (based on AiringDuration).
				if(airing.has_key('AiringDuration')):
					duration = float(airing['AiringDuration'] // 1000)
					endTime = startTime + duration
					item.SetProperty('AiringEndTime', strftime('%H:%M', time.localtime(endTime)))
					item.SetProperty('AiringEndTimeMillis', str(airing['AiringEndTime']))
					scheduleEndtime = float(airing['ScheduleEndTime'] // 1000)
					item.SetProperty('ScheduleEndTime', strftime('%H:%M', time.localtime(scheduleEndtime)))
					item.SetProperty('ScheduleEndTimeMillis', str(airing['ScheduleEndTime']))
				else:
					item.SetProperty('AiringEndTime', 'Unknown')
					item.SetProperty('AiringEndTimeMillis', '0')
					item.SetProperty('ScheduleEndTime', 'Unknown')
					item.SetProperty('ScheduleEndTimeMillis', '0')
			else:
				item.SetProperty('AiringStartTimeMillis', '0')
				item.SetProperty('AiringEndTimeMillis', '0')
				item.SetProperty('ScheduleEndTimeMillis', '0')
		return item
	except IndexError:
		mc.LogDebug('recordings.py: Received MediaFile with no file segments [%d]' % mf['MediaFileID'])
		return None

def _movieMediaFileToListItem(mf):
	pass

def mediaFileListToListItemList(list):
	'''Convert a list of Sage MediaFile JSON objects to a list of Boxee ListItem objects.

		  list: A list of dictionary objects; each dictionary represents a Sage MediaFile JSON object
		return: A list of Boxee ListItem objects
	'''
	items = []
	for i in list:
		item = mediaFileToListItem(i)
		if(item != None):
			items.append(item)
	return items

def mediaFileListToListItems(list):
	'''Convert a list of Sage MediaFile JSON objects to a Boxee ListItems object.

		  list: A list of dictionary objects; each dictionary represents a Sage MediaFile
		return: A Boxee ListItems object; the contents is each dictionary converted to a Boxee ListItem
	'''
	items = mc.ListItems()
	for i in list:
		item = mediaFileToListItem(i)
		if(item != None):
			items.append(item)
	return items

def _getHoursMinutes(seconds):
	'''Convert seconds to hours and minutes.'''
	m, s = divmod(seconds, 60)
	if (s > 30):
		m += 1
	h, m = divmod(m, 60)
	mstring = (m > 0) and ('%d ' % (m)) + _getPlural(m, 'minute') or ''
	hstring = (h > 0) and ('%d ' % (h)) + _getPlural(h, 'hour') or ''
	return ('%s %s' % (hstring, mstring)).strip()

def _getPlural(count, label):
	return label + ((count > 1) and 's' or '')
	
def addMultiSegmentItemToPlaylist(item, playlist):
	numberOfSegments = int(item.GetProperty('NumberOfSegments'))
	for i in range(0, numberOfSegments):
		newItem = mc.ListItem(mc.ListItem.MEDIA_VIDEO_EPISODE)
		newItem.SetAddToHistory(False)
		newItem.SetLabel(item.GetLabel())
		newItem.SetTitle(item.GetTitle())
		newItem.SetTVShowTitle(item.GetTVShowTitle())
		newItem.SetPath(item.GetProperty("Segment"+str(i)))
		newItem.SetContentType(item.GetContentType())
		mc.LogDebug("SageBoxee: Added newItem to playlist")
		playlist.Add(newItem)
	return playlist
	
def getFilteredMediaFileTitles(mask, includeFilters, excludeFilters, api):

	# Start with all complete MediaFiles.
	expr = 'FilterByMethod(GetMediaFiles("%s"), "IsCompleteRecording", true, true)' % mask
	
	# Add include filters.
	if includeFilters != '':
		includes = includeFilters.split('|')
		for include in includes:
			expr = 'FilterByBoolMethod(' + expr + ',"%s", true)' % include
			mc.LogDebug("SageBoxee: Show expr after adding include filter " + expr)
			
	# Add exclude filters.
	if excludeFilters != '':
		excludes = excludeFilters.split('|')
		for exclude in excludes:
			expr = 'FilterByBoolMethod(' + expr + ',"%s", false)' % exclude
			mc.LogDebug("SageBoxee: Show expr after adding exclude filter " + expr)
	
	# Group by MediaTitle.
	expr = 'GroupByMethod(' + expr + ',"GetMediaTitle")'
	
	# Get the keyset.
	expr = 'java_util_Map_keySet(' + expr + ')'
	
	# Sort them alphabetically.
	expr = 'Sort(' + expr + ',false,"Natural")'
	
	return api.EvaluateExpression(expr)
	
def getFilteredEpisodes(title, mask, includeFilters, excludeFilters, sortStyle, api):
	expr = 'FilterByBoolMethod(FilterByMethod(GetMediaFiles("%s"), "GetMediaTitle", "%s", true), "IsCompleteRecording", true)' % (mask, title)
	
	# Add include filters.
	if includeFilters != '':
		includes = includeFilters.split('|')
		for include in includes:
			expr = 'FilterByBoolMethod(' + expr + ',"%s", true)' % include
			mc.LogDebug("SageBoxee: Episode expr after adding include filter " + expr)
			
	# Add exclude filters.
	if excludeFilters != '':
		excludes = excludeFilters.split('|')
		for exclude in excludes:
			expr = 'FilterByBoolMethod(' + expr + ',"%s", false)' % exclude
			mc.LogDebug("SageBoxee: Episode expr after adding exclude filter " + expr)

	# Sort.
	rev = sortStyle.find("eversed") != -1
	reversed = str(rev).lower()
	mc.LogDebug("SageBoxee: Episode sort style is " + sortStyle + ". Reversed is " + str(reversed))
	
	if sortStyle.startswith("Show ID"):
		expr = 'SortLexical(' + expr + ', %s, "GetAiringTitle")' % reversed
		expr = 'Sort(' + expr + ', %s, "GetShowExternalID")' % reversed
	elif sortStyle.startswith("Date"):
		expr = 'SortLexical(' + expr + ', %s, "GetAiringTitle")' % reversed
		expr = 'Sort(' + expr + ', %s, "GetAiringStartTime")' % reversed
	elif sortStyle.startswith("Original Air Date"):
		expr = 'SortLexical(' + expr + ', %s, "GetAiringTitle")' % reversed
		expr = 'Sort(' + expr + ', %s, "GetOriginalAiringDate")' % reversed
	elif sortStyle.startswith("Season/Episode"):
		expr = 'Sort(' + expr + ', %s, "GetOriginalAiringDate")' % reversed
		expr = 'Sort(' + expr + ', %s, "GetShowEpisodeNumber")' % reversed
		expr = 'Sort(' + expr + ', %s, "GetShowSeasonNumber")' % reversed
	else:	
		# "Title" is default.
		expr = 'SortLexical(' + expr + ', %s, "GetShowEpisode")' % reversed
		expr = 'SortLexical(' + expr + ', %s, "GetAiringTitle")' % reversed

	mc.LogDebug("SageBoxee: Episode expr after adding sort methods " + expr)

	return api.EvaluateExpression(expr)
	
def createEmptyListItems():
	items = mc.ListItems()
	item = mc.ListItem(mc.ListItem.MEDIA_VIDEO_EPISODE)
	item.SetLabel('Empty')
	item.SetTVShowTitle('Empty')
	item.SetAddToHistory(False)
	item.SetProperty('IsDummy', 'True')
	items.append(item)
	return items
	
def setPercentWatched(item, api, granularity=10):
	mediaFileID = item.GetProperty('MediaFileID')
	if mediaFileID == None or mediaFileID == '':
		mc.LogDebug('SageBoxee: Item %s does not have MediaFile.' % item.GetLabel())
		item.SetProperty('PercentWatched', '0')
		return item
		
	watched = item.GetProperty('IsWatched').lower()
	if watched == 'true':
		mc.LogDebug('SageBoxee: File is completely watched.')
		item.SetProperty('PercentWatched', '100')
		item.SetProperty('ProgressBar', '100.png')	
		return item
		
	# Calculate the amount watched.
	expr = '(GetWatchedDuration(GetMediaFileForID(%s))*1.0) / (GetAiringDuration(GetMediaFileForID(%s))*1.0)' % (mediaFileID, mediaFileID)
	percent = float(api.EvaluateExpression(expr))
	
	#expr = 'GetWatchedDuration(GetMediaFileForID(%s))' % mediaFileID
	#watched = float(api.EvaluateExpression(expr))
	
	#expr = 'GetAiringDuration(GetMediaFileForID(%s))' % mediaFileID
	#duration = float(api.EvaluateExpression(expr))
	
	#percent = watched/duration
	
	# Round it based on granularity.
	progress = int(round((percent*100)/granularity)) * granularity
	item.SetProperty('PercentWatched', str(progress))
	item.SetProperty('ProgressBar', '%s.png' % str(progress))
	
	mc.LogDebug('SageBoxee: "%s" is %s percent watched.' % (item.GetLabel(), item.GetProperty('PercentWatched')))
	return item
	
def setPercentWatchedForItems(items, api):
	if items == None or len(items)==0:
		mc.LogDebug("SageBoxee: No items to setPercentWatched.")
		return items
	newItems = mc.ListItems()
	for item in items:
		newItems.append(setPercentWatched(item, api))
	return newItems